﻿/**
 * Copyright (c) 2013 Nokia Corporation.
 */

using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TweetSharp;

namespace Dradis
{
    /// <summary>
    /// This class manages the application specific settings.
    /// </summary>
    class ApplicationSettings
    {
        // Constants
        private const String UserNameId = "UserName";
        private const String UserObjectTypeId = "UserObjectType";
        private const String LocationAllowedId = "LocationAllowed";
        private const String BroadcastingAllowedId = "BroadcastingAllowed";
        private const String LastLocationId = "LastLocation";
        private const String TwitterTokenId = "TwitterToken";
        private const String TwitterChannelId = "TwitterChannel";
        private const String FirstLaunchId = "FirstLaunch";

        private const String DefaultTwitterChannel = "spaceship2013";

        // Members and properties
        private static ApplicationSettings _instance = null;
        private IsolatedStorageSettings _storage = null;

        public String UserName { get; set; }
        public User.ObjectType UserObjectType { get; set; }
        public bool LocationAllowed { get; set; }
        public bool BroadcastingAllowed { get; set; }
        public GeoCoordinate LastLocation { get; set; }
        public OAuthAccessToken TwitterToken { get; set; }
        public String TwitterChannel { get; set; }
        public bool FirstLaunch { get; set; }

        /// <summary>
        /// When the settings have been changed.
        /// </summary>
        public event EventHandler SettingsChanged;

        /// <summary>
        /// Getter for the singleton instance of this class.
        /// </summary>
        /// <returns>The singleton instance of this class.</returns>
        public static ApplicationSettings GetInstance()
        {
            if (_instance == null)
            {
                _instance = new ApplicationSettings();
                _instance._storage = IsolatedStorageSettings.ApplicationSettings;
            }

            return _instance;
        }

        /// <summary>
        /// Creates a copy of the current global settings but without the
        /// storage. You cannot load or save settings using the copy.
        /// </summary>
        /// <returns>A newly created copy of the current settings.</returns>
        public static ApplicationSettings GetCopy()
        {
            ApplicationSettings original = GetInstance();
            ApplicationSettings copy = new ApplicationSettings();
            _instance.CopyProperties(ref copy);
            return copy;
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        private ApplicationSettings()
        {
            ApplyDefaultSettings();
        }

        /// <summary>
        /// Loads the application settings from the persistent storage.
        /// </summary>
        /// <returns>True if successful, false otherwise.</returns>
        public bool Load()
        {
            if (_storage == null || !_storage.Contains(UserNameId))
            {
                return false;
            }

            try
            {
                UserName = (String)_storage[UserNameId];
                UserObjectType = (User.ObjectType)_storage[UserObjectTypeId];
                LocationAllowed = (bool)_storage[LocationAllowedId];
                BroadcastingAllowed = (bool)_storage[BroadcastingAllowedId];
                LastLocation = (GeoCoordinate)_storage[LastLocationId];
                TwitterToken = (OAuthAccessToken)_storage[TwitterTokenId];
                TwitterChannel = (String)_storage[TwitterChannelId];
                FirstLaunch = (bool)_storage[FirstLaunchId];
            }
            catch (KeyNotFoundException e)
            {
                Debug.WriteLine("ApplicationSettings::Load(): Some items not loaded: "
                    + e.ToString());
                ApplyDefaultSettings();
                return false;
            }
            catch (InvalidCastException e)
            {
                Debug.WriteLine("ApplicationSettings::Load(): Some items not loaded: "
                    + e.ToString());
                ApplyDefaultSettings();
                return false;
            }

            return true;
        }

        /// <summary>
        /// Saves the application settings to the persistent storage.
        /// </summary>
        /// <returns>True if successful, false otherwise.</returns>
        public bool Save()
        {
            Debug.WriteLine("ApplicationSettings::Save(): " + ToString());

            if (_storage == null)
            {
                return false;
            }

            _storage[UserNameId] = UserName;
            _storage[UserObjectTypeId] = UserObjectType;
            _storage[LocationAllowedId] = LocationAllowed;
            _storage[BroadcastingAllowedId] = BroadcastingAllowed;
            _storage[LastLocationId] = LastLocation;
            _storage[TwitterTokenId] = TwitterToken;
            _storage[TwitterChannelId] = TwitterChannel;
            _storage[FirstLaunchId] = FirstLaunch;
            return true;
        }

        /// <summary>
        /// Notifies listeners that the settings have been changed.
        /// </summary>
        public void NotifySettingsChanged()
        {
            EventHandler handler = this.SettingsChanged;

            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Copies the settings from the given instance to the global, static
        /// settings.
        /// </summary>
        /// <param name="settings">The instance containing the new settings.</param>
        public void Set(ApplicationSettings settings)
        {
            if (settings != null && _instance != null)
            {
                Debug.WriteLine("ApplicationSettings::Set(): " + settings.ToString());
                settings.CopyProperties(ref _instance);
            }
        }

        /// <summary>
        /// Copies the property values of this instance into the given one.
        /// Note that some properties have been omitted.
        /// </summary>
        /// <param name="destination">Where the values are copied to.</param>
        private void CopyProperties(ref ApplicationSettings destination)
        {
            destination.UserName = UserName;
            destination.UserObjectType = UserObjectType;
            destination.LocationAllowed = LocationAllowed;
            destination.BroadcastingAllowed = BroadcastingAllowed;
            destination.LastLocation = LastLocation;
            destination.TwitterToken = TwitterToken;
            destination.TwitterChannel = TwitterChannel;
        }

        /// <summary>
        /// Creates and returns a string containing the properties of this
        /// instance.
        /// </summary>
        /// <returns>The current settings in a string.</returns>
        public override string ToString()
        {
            return UserName + "; " + UserObjectType + "; " + LocationAllowed
                + "; " + BroadcastingAllowed + "; " + LastLocation + "; "
                + TwitterToken + "; " + TwitterChannel + "; " + FirstLaunch;
        }

        /// <summary>
        /// Applies the default settings.
        /// </summary>
        private void ApplyDefaultSettings()
        {
            UserName = new Random(new System.DateTime().Millisecond).Next(1000000).ToString();
            UserObjectType = User.ObjectType.Raider;
            LocationAllowed = false;
            BroadcastingAllowed = false;
            LastLocation = null;
            TwitterToken = null;
            TwitterChannel = DefaultTwitterChannel;
            FirstLaunch = true;
        }
    }
}
